package com.sunwayworld.basemodule.samplemanage.samplehandle.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.basemodule.common.auditrecord.service.LimsAuditRecordService;
import com.sunwayworld.basemodule.common.constant.LimsConstant;
import com.sunwayworld.basemodule.samplemanage.change.bean.LimsLocationChangeBean;
import com.sunwayworld.basemodule.samplemanage.change.service.LimsLocationChangeService;
import com.sunwayworld.basemodule.samplemanage.location.bean.LimsLocationBoardHoleBean;
import com.sunwayworld.basemodule.samplemanage.location.service.LimsLocationBoardHoleService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.basemodule.samplemanage.samplehandle.bean.LimsSampleHandleRelationBean;
import com.sunwayworld.basemodule.samplemanage.samplehandle.service.LimsSampleHandleRelationService;
import com.sunwayworld.framework.constant.Constant;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.utils.ArrayUtils;
import com.sunwayworld.framework.utils.CollectionUtils;
import com.sunwayworld.framework.utils.StringUtils;
import com.sunwayworld.module.sys.bpmn.bean.CoreBpmnInstanceStatusDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.sunwayworld.framework.spring.annotation.GikamBean;

import com.sunwayworld.basemodule.samplemanage.samplehandle.dao.LimsSampleHandleDao;
import com.sunwayworld.basemodule.samplemanage.samplehandle.bean.LimsSampleHandleBean;
import com.sunwayworld.basemodule.samplemanage.samplehandle.service.LimsSampleHandleService;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;

import java.util.*;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsSampleHandleServiceImpl implements LimsSampleHandleService {

    @Autowired
    private LimsSampleHandleDao limsSampleHandleDao;

    @Autowired
    @Lazy
    private LimsSampleService sampleService;

    @Autowired
    @Lazy
    private LimsLocationChangeService locationChangeService;

    @Autowired
    @Lazy
    private LimsLocationBoardHoleService holeService;

    @Autowired
    @Lazy
    private LimsAuditRecordService auditRecordService;

    @Autowired
    @Lazy
    private LimsSampleHandleRelationService sampleHandleRelationService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsSampleHandleDao getDao() {
        return limsSampleHandleDao;
    }

    @Override
    @Transactional
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        LimsSampleHandleBean limsSampleHandle = jsonWrapper.parseUnique(LimsSampleHandleBean.class);
        limsSampleHandle.setId(ApplicationContextHelper.getNextIdentity());
        limsSampleHandle.setHandleCode(ApplicationContextHelper.getNextSequence(getDao().getTable(),"H"));
        getDao().insert(limsSampleHandle);
        return limsSampleHandle.getId();
    }

    @Transactional
    @Override
    public void delete(RestJsonWrapperBean wrapper) {
        List<LimsSampleHandleBean> deleteList = wrapper.parse(this.getDao().getType());
        List<Long> handleIds = deleteList.stream().map(LimsSampleHandleBean::getId).collect(Collectors.toList());
        deleteList = this.selectListByFilter(SearchFilter.instance().match("id", handleIds).filter(MatchPattern.OR));
        if (deleteList.isEmpty()) {
            return;
        }
        List<LimsSampleHandleRelationBean> handleRelationBeans = sampleHandleRelationService.selectListByFilter(SearchFilter.instance().match("handleId", handleIds).filter(MatchPattern.OR));
        if (!handleRelationBeans.isEmpty()) {
            List<Long> sampleIds = handleRelationBeans.stream().map(LimsSampleHandleRelationBean::getSampleId).distinct().collect(Collectors.toList());
            List<Long> relationIds = handleRelationBeans.stream().map(LimsSampleHandleRelationBean::getId).collect(Collectors.toList());
            if (!sampleIds.isEmpty()) {
                List<LimsSampleBean> sampleBeans = sampleService.selectListByIds(sampleIds);
                if (!sampleBeans.isEmpty()) {
                    sampleBeans.forEach(s -> {
                        s.setSampleHandleId(null);
                        // 出库、销毁、返样申请单删除后，变回入库完成状态
                        if ("enter".equalsIgnoreCase(s.getHandleType())) {
                            if ("2".equalsIgnoreCase(s.getInHandle())) {
                                s.setHandleType("outDone"); // 出库的变成出库完成状态
                            } else {
                                s.setHandleType("wait"); // 衍生物的变回待入库状态
                            }
                        } else {
                            s.setHandleType("enterDone");
                        }
                    });
                    sampleService.getDao().update(sampleBeans, "sampleHandleId", "handleType");
                }
            }
            sampleHandleRelationService.getDao().deleteByIdList(relationIds);
        }
        getDao().deleteByIdList(handleIds);
    }

    @Override
    @Transactional
    public void addSample(RestJsonWrapperBean wrapper) {
        List<LimsSampleBean> samples = wrapper.parse(LimsSampleBean.class);
        sampleService.getDao().update(samples, "sampleHandleId", "handleType");
        Long handleId = samples.get(0).getSampleHandleId();
        List<LimsSampleHandleRelationBean> relationBeans = new ArrayList<>();
        samples.forEach(s -> {
            LimsSampleHandleRelationBean relationBean = new LimsSampleHandleRelationBean();
            relationBean.setId(ApplicationContextHelper.getNextIdentity());
            relationBean.setHandleId(handleId);
            relationBean.setSampleId(s.getId());
            relationBeans.add(relationBean);
        });
        sampleHandleRelationService.getDao().insert(relationBeans);
    }

    @Override
    @Transactional
    public void deleteSample(RestJsonWrapperBean wrapper) {
        List<LimsSampleBean> sampleBeans = wrapper.parse(LimsSampleBean.class);
        List<LimsSampleHandleRelationBean> relationBeans = new ArrayList<>();
        sampleBeans.forEach(ss -> {
            LimsSampleHandleRelationBean relationBean = new LimsSampleHandleRelationBean();
            relationBean.setHandleId(ss.getSampleHandleId());
            relationBean.setSampleId(ss.getId());
            relationBeans.add(relationBean);

            ss.setSampleHandleId(null);
            // 入库申请的删除后，清空|出库、销毁、返样申请单删除后，变回入库完成状态
            if ("enter".equalsIgnoreCase(ss.getHandleType())){
                if ("2".equalsIgnoreCase(ss.getInHandle())) {
                    ss.setHandleType("outDone");
                } else {
                    ss.setHandleType("wait");
                }
            }else{
                ss.setHandleType("enterDone");
            }
        });
        sampleService.getDao().update(sampleBeans, "sampleHandleId", "handleType");
        sampleHandleRelationService.getDao().deleteBy(relationBeans, "handleId", "sampleId");
    }

    @Override
    public JSONObject checkSampleLocations(RestJsonWrapperBean wrapper) {
        JSONObject json = new JSONObject();
        List<LimsSampleHandleBean> handleBeans = wrapper.parse(LimsSampleHandleBean.class);
        StringBuffer message = new StringBuffer();
        if (!handleBeans.isEmpty()) {
            List<Long> handleIds = handleBeans.stream().map(LimsSampleHandleBean::getId).collect(Collectors.toList());
            List<LimsSampleBean> sampleBeans = sampleService.selectListByFilter(SearchFilter.instance().match("sampleHandleId", handleIds).filter(MatchPattern.OR));
            handleBeans.forEach(i -> {
                List<LimsSampleBean> filter = sampleBeans.stream().filter(s -> s.getSampleHandleId().equals(i.getId())).collect(Collectors.toList());
                filter.forEach(s -> {
                    if (StringUtils.isEmpty(s.getLocations())) {
                        message.append(s.getSampleCode()).append("<br/>");
                    }
                });
            });
        }
        if (message.length() > 0) {
            json.put("message", message.toString());
        }

        return json;
    }

    @Transactional
    @Override
    public List<CoreBpmnInstanceStatusDTO<Long>> startProcess(RestJsonWrapperBean wrapper) {
        List<LimsSampleHandleBean> itemList = wrapper.parse(LimsSampleHandleBean.class);
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            List<CoreBpmnInstanceStatusDTO<Long>> instanceStatusDTOS = LimsSampleHandleService.super.startProcess(wrapper);
            List<Long> ids = itemList.stream().map(LimsSampleHandleBean::getId).collect(Collectors.toList());
            List<LimsSampleHandleBean> handleBeans = selectListByFilter(SearchFilter.instance().match("id", ids).filter(MatchPattern.OR));
            List<LimsSampleBean> limsSampleBeans = sampleService.selectListByFilter(SearchFilter.instance().match("sampleHandleId", ids).filter(MatchPattern.OR));
            String handleType = handleBeans.get(0).getHandleType();
            for (LimsSampleHandleBean handleBean : handleBeans) {
                List<LimsSampleBean> sampleBeans = limsSampleBeans.stream().filter(s -> s.getSampleHandleId().equals(handleBean.getId())).collect(Collectors.toList());
                sampleBeans.forEach(sample -> {
                    sample.setHandleType(handleType + "Audit");  // 修改样本处置状态为  XXX 审核中
                });
            }
            sampleService.getDao().update(limsSampleBeans, "handleType");

            // 加操作记录
            List<Long> sampleIds = limsSampleBeans.stream().map(LimsSampleBean::getId).collect(Collectors.toList());
            String message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_warehousing_application"); // 入库申请
            if ("out".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_issue_application");  // 出库申请
            } else if ("destroy".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_destruction_Application");  // 销毁申请
            } else if ("back".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_return_customer_application");  // 返样申请
            }
            auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", message, I18nHelper.getMessage("GIKAM.MODAL.SUBMIT"), wrapper.getParamValue("bpmn_comment"));

            return instanceStatusDTOS;
        }
    }


    @Transactional
    @Override
    public List<CoreBpmnInstanceStatusDTO<Long>> completeTask(RestJsonWrapperBean wrapper) {
        List<LimsSampleHandleBean> itemList = wrapper.parse(LimsSampleHandleBean.class);
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            List<CoreBpmnInstanceStatusDTO<Long>> instanceStatusDTOS = LimsSampleHandleService.super.completeTask(wrapper);
            List<Long> ids = itemList.stream().map(LimsSampleHandleBean::getId).collect(Collectors.toList());
            List<LimsSampleHandleBean> handleBeans = selectListByFilter(SearchFilter.instance().match("id", ids).filter(MatchPattern.OR));
            List<LimsSampleBean> limsSampleBeans = sampleService.selectListByFilter(SearchFilter.instance().match("sampleHandleId", ids).filter(MatchPattern.OR));
            String handleType = handleBeans.get(0).getHandleType();
            String inHandle = "0";
            if ("enter".equalsIgnoreCase(handleType)) {
                inHandle = "1";  // 入库
            } else if ("out".equalsIgnoreCase(handleType)) {
                inHandle = "2"; // 出库
            } else if ("destroy".equalsIgnoreCase(handleType)) {
                inHandle = "4"; // 销毁
            } else if ("back".equalsIgnoreCase(handleType)) {
                inHandle = "5"; // 返样
            }
            for (LimsSampleBean sample : limsSampleBeans) {
                sample.setHandleType(handleType + "Done"); // 修改样本处置状态为  XXX 完成
                sample.setInHandle(inHandle);
            }

            List<String> updateColumns = new ArrayList<>(Arrays.asList("handleType", "inHandle"));

            if ("enter".equalsIgnoreCase(handleType)) {
                List<LimsSampleHandleRelationBean> handleRelationBeans = sampleHandleRelationService.selectListByFilter(SearchFilter.instance().match("handleId", ids).filter(MatchPattern.OR));
                for (LimsSampleHandleBean handleBean : handleBeans) {
                    List<LimsSampleBean> sampleBeans = limsSampleBeans.stream().filter(s -> s.getSampleHandleId().equals(handleBean.getId())).collect(Collectors.toList());
                    sampleBeans.forEach(sample -> handleRelationBeans.stream().filter(i -> i.getHandleId().equals(handleBean.getId())
                            && i.getSampleId().equals(sample.getId())).findAny().ifPresent(hr -> {
                        // sample.setSampleVolume(hr.getSampleVolume());
                        // sample.setSampleConcentration(hr.getSampleConcentration());
                        sample.setRestCount(hr.getRestCount());
                    }));
                }
                updateColumns.addAll(Arrays.asList("restCount"));
            }

            // 加操作记录
            List<Long> sampleIds = limsSampleBeans.stream().map(LimsSampleBean::getId).collect(Collectors.toList());
            String message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_warehousing_approval"); // 入库审核
            if ("out".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_issue_approval");  // 出库审核
            } else if ("destroy".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_destruction_approval");  // 销毁审核
            } else if ("back".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_return_customer_approval");  // 返样审核
            }
            auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", message, I18nHelper.getMessage("GIKAM.WORKFLOW.BUTTON.PASS"), wrapper.getParamValue("bpmn_comment"));

            //样本销毁、返还客户  审核通过后去除样本表的板孔位信息、孔位表的占用信息  20220429
            if ("destroy".equalsIgnoreCase(handleType) || "back".equalsIgnoreCase(handleType) || "out".equalsIgnoreCase(handleType)) {
                List<Long> sampleids = limsSampleBeans.stream().map(LimsSampleBean::getId).collect(Collectors.toList());
                List<LimsLocationBoardHoleBean> boardHoleBeans = holeService.selectListBySampleIds(sampleids);
                List<Long> changeIds = ApplicationContextHelper.getNextIdentityList(sampleids.size());

                List<LimsLocationChangeBean> oldLocationChangeBeans = locationChangeService.selectListByFilter(SearchFilter.instance()
                        .match("businessId", sampleids).filter(MatchPattern.OR))
                        .stream().sorted(Comparator.comparing(LimsLocationChangeBean::getCreatedTime).reversed()).collect(Collectors.toList());
                List<LimsLocationChangeBean> insertChangeList = new ArrayList<>();
                limsSampleBeans.forEach(s -> {
                    s.setBoardHoleId(null);
                    s.setBoardId(null);
                    s.setLocations(null);
                    if (!oldLocationChangeBeans.isEmpty()){
                        Optional<LimsLocationChangeBean> first = oldLocationChangeBeans.stream().filter(old -> StringUtils.equals(old.getBusinessId(), s.getId().toString())).findFirst();
                        if (first.isPresent()){
                            LimsLocationChangeBean locationChangeBean = new LimsLocationChangeBean();
                            locationChangeBean.setId(changeIds.remove(0));
                            locationChangeBean.setBusinessCode("T_LIMS_SAMPLE");
                            locationChangeBean.setBusinessId(s.getId().toString());
                            locationChangeBean.setOldValue(oldLocationChangeBeans.get(0).getNewValue());
                            insertChangeList.add(locationChangeBean);
                        }
                    }
                });
                updateColumns.addAll(ArrayUtils.asList("boardId", "boardHoleId", "locations"));

                boardHoleBeans.forEach(holeBean -> {
                    holeBean.setSampleId(null);
                    holeBean.setStockType(LimsConstant.HOLE_STOCKTYPE_FREE);
                });
                holeService.getDao().update(boardHoleBeans, "sampleId", "stockType");

                if (!insertChangeList.isEmpty()){
                    locationChangeService.getDao().insert(insertChangeList);
                }
            }
            sampleService.getDao().update(limsSampleBeans, updateColumns);
            return instanceStatusDTOS;
        }
    }

    @Override
    public List<CoreBpmnInstanceStatusDTO<Long>> rejectTask(RestJsonWrapperBean wrapper) {
        List<LimsSampleHandleBean> itemList = wrapper.parse(LimsSampleHandleBean.class);
        if (itemList.isEmpty()) {
            return CollectionUtils.emptyList();
        } else {
            List<CoreBpmnInstanceStatusDTO<Long>> instanceStatusDTOS = LimsSampleHandleService.super.rejectTask(wrapper);
            List<Long> ids = itemList.stream().map(LimsSampleHandleBean::getId).collect(Collectors.toList());
            List<LimsSampleHandleBean> handleBeans = selectListByFilter(SearchFilter.instance().match("id", ids).filter(MatchPattern.OR));
            List<LimsSampleBean> limsSampleBeans = sampleService.selectListByFilter(SearchFilter.instance().match("sampleHandleId", ids).filter(MatchPattern.OR));
            String handleType = handleBeans.get(0).getHandleType();
            for (LimsSampleHandleBean handleBean : handleBeans) {
                List<LimsSampleBean> sampleBeans = limsSampleBeans.stream().filter(s -> s.getSampleHandleId().equals(handleBean.getId())).collect(Collectors.toList());
                sampleBeans.forEach(sample -> {
                    sample.setHandleType(handleType);  // 修改样本处置状态
                });
            }
            sampleService.getDao().update(limsSampleBeans, "handleType");

            // 加操作记录
            List<Long> sampleIds = limsSampleBeans.stream().map(LimsSampleBean::getId).collect(Collectors.toList());
            String message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_warehousing_approval"); // 入库审核
            if ("out".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_issue_approval");  // 出库审核
            } else if ("destroy".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_destruction_approval");  // 销毁审核
            } else if ("back".equalsIgnoreCase(handleType)) {
                message = I18nHelper.getMessage("CORE.MENU.MENUNAME.Sample_return_customer_approval");  // 返样审核
            }
            auditRecordService.insertAuditRecords(sampleIds, "T_LIMS_SAMPLE", message, I18nHelper.getMessage("GIKAM.WORKFLOW.BUTTON.REJECT"), wrapper.getParamValue("bpmn_comment"));

            return instanceStatusDTOS;
        }
    }
}
